home *** CD-ROM | disk | FTP | other *** search
/ Qoole for Quake / Qoole for Quake (USA) / Qoole for Quake (USA).bin / Tutorial / HTML / QUBE.ZIP / SRC / MAP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-05  |  10.5 KB  |  575 lines

  1. /* map.c */
  2.  
  3. #include "bsp5.h"
  4.  
  5. int            nummapbrushes;
  6. mbrush_t    mapbrushes[MAX_MAP_BRUSHES];
  7.  
  8. int            num_entities;
  9. entity_t    entities[MAX_MAP_ENTITIES];
  10.  
  11. int            nummiptex;
  12. char        miptex[MAX_MAP_TEXINFO][16];
  13.  
  14.  
  15. /*============================================================================ */
  16.  
  17. /*
  18. ===============
  19. FindMiptex
  20.  
  21. ===============
  22. */
  23. int FindMiptex (char *name)
  24. {
  25.     int        i;
  26.     
  27.     for (i=0 ; i<nummiptex ; i++)
  28.     {
  29.         if (!strcmp (name, miptex[i]))
  30.             return i;
  31.     }
  32.     if (nummiptex == MAX_MAP_TEXINFO)
  33.         Error ("nummiptex == MAX_MAP_TEXINFO");
  34.     strcpy (miptex[i], name);
  35.     nummiptex++;
  36.     return i;
  37. }
  38.  
  39. /*
  40. ===============
  41. FindTexinfo
  42.  
  43. Returns a global texinfo number
  44. ===============
  45. */
  46. int    FindTexinfo (texinfo_t *t)
  47. {
  48.     int            i, j;
  49.     texinfo_t    *tex;
  50.         
  51. /* set the special flag */
  52.     if (miptex[t->miptex][0] == '*' 
  53.     || !Q_strncasecmp (miptex[t->miptex], "sky",3) )
  54.         t->flags |= TEX_SPECIAL;
  55.  
  56.  
  57.     tex = texinfo;    
  58.     for (i=0 ; i<numtexinfo;i++, tex++)
  59.     {
  60.         if (t->miptex != tex->miptex)
  61.             continue;
  62.         if (t->flags != tex->flags)
  63.             continue;
  64.         
  65.         for (j=0 ; j<8 ; j++)
  66.             if (t->vecs[0][j] != tex->vecs[0][j])
  67.                 break;
  68.         if (j != 8)
  69.             continue;
  70.             
  71.         return i;
  72.     }
  73.     
  74. /* allocate a new texture */
  75.     if (numtexinfo == MAX_MAP_TEXINFO)
  76.         Error ("numtexinfo == MAX_MAP_TEXINFO");
  77.     texinfo[i] = *t;
  78.     numtexinfo++;
  79.  
  80.     return i;
  81. }
  82.  
  83.  
  84. /*============================================================================ */
  85.  
  86. #define    MAXTOKEN    128
  87.  
  88. char    token[MAXTOKEN];
  89. qboolean    unget;
  90. char    *script_p;
  91. int        scriptline;
  92.  
  93. void    StartTokenParsing (char *data)
  94. {
  95.     scriptline = 1;
  96.     script_p = data;
  97.     unget = false;
  98. }
  99.  
  100. qboolean GetToken (qboolean crossline)
  101. {
  102.     char    *token_p;
  103.  
  104.     if (unget)                         /* is a token allready waiting? */
  105.         return true;
  106.  
  107. /* */
  108. /* skip space */
  109. /* */
  110. skipspace:
  111.     while (*script_p <= 32)
  112.     {
  113.         if (!*script_p)
  114.         {
  115.             if (!crossline)
  116.                 Error ("Line %i is incomplete",scriptline);
  117.             return false;
  118.         }
  119.         if (*script_p++ == '\n')
  120.         {
  121.             if (!crossline)
  122.                 Error ("Line %i is incomplete",scriptline);
  123.             scriptline++;
  124.         }
  125.     }
  126.  
  127.     if (script_p[0] == '/' && script_p[1] == '/')    /* comment field */
  128.     {
  129.         if (!crossline)
  130.             Error ("Line %i is incomplete\n",scriptline);
  131.         while (*script_p++ != '\n')
  132.             if (!*script_p)
  133.             {
  134.                 if (!crossline)
  135.                     Error ("Line %i is incomplete",scriptline);
  136.                 return false;
  137.             }
  138.         goto skipspace;
  139.     }
  140.  
  141. /* */
  142. /* copy token */
  143. /* */
  144.     token_p = token;
  145.  
  146.     if (*script_p == '"')
  147.     {
  148.         script_p++;
  149.         while ( *script_p != '"' )
  150.         {
  151.             if (!*script_p)
  152.                 Error ("EOF inside quoted token");
  153.             *token_p++ = *script_p++;
  154.             if (token_p > &token[MAXTOKEN-1])
  155.                 Error ("Token too large on line %i",scriptline);
  156.         }
  157.         script_p++;
  158.     }
  159.     else while ( *script_p > 32 )
  160.     {
  161.         *token_p++ = *script_p++;
  162.         if (token_p > &token[MAXTOKEN-1])
  163.             Error ("Token too large on line %i",scriptline);
  164.     }
  165.  
  166.     *token_p = 0;
  167.     
  168.     return true;
  169. }
  170.  
  171. void UngetToken ()
  172. {
  173.     unget = true;
  174. }
  175.  
  176.  
  177. /*============================================================================ */
  178.  
  179. entity_t    *mapent;
  180.  
  181. /*
  182. =================
  183. ParseEpair
  184. =================
  185. */
  186. void ParseEpair (void)
  187. {
  188.     epair_t    *e;
  189.     
  190.     e = malloc (sizeof(epair_t));
  191.     memset (e, 0, sizeof(epair_t));
  192.     e->next = mapent->epairs;
  193.     mapent->epairs = e;
  194.     
  195.     if (strlen(token) >= MAX_KEY-1)
  196.         Error ("ParseEpar: token too long");
  197.     strcpy (e->key, token);
  198.     GetToken (false);
  199.     if (strlen(token) >= MAX_VALUE-1)
  200.         Error ("ParseEpar: token too long");
  201.     strcpy (e->value, token);
  202. }
  203.  
  204. /*============================================================================ */
  205.  
  206.  
  207. /*
  208. ==================
  209. textureAxisFromPlane
  210. ==================
  211. */
  212. vec3_t    baseaxis[18] =
  213. {
  214. {0,0,1}, {1,0,0}, {0,-1,0},            /* floor */
  215. {0,0,-1}, {1,0,0}, {0,-1,0},        /* ceiling */
  216. {1,0,0}, {0,1,0}, {0,0,-1},            /* west wall */
  217. {-1,0,0}, {0,1,0}, {0,0,-1},        /* east wall */
  218. {0,1,0}, {1,0,0}, {0,0,-1},            /* south wall */
  219. {0,-1,0}, {1,0,0}, {0,0,-1}            /* north wall */
  220. };
  221.  
  222. void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
  223. {
  224.     int        bestaxis;
  225.     float    dot,best;
  226.     int        i;
  227.     
  228.     best = 0;
  229.     bestaxis = 0;
  230.     
  231.     for (i=0 ; i<6 ; i++)
  232.     {
  233.         dot = DotProduct (pln->normal, baseaxis[i*3]);
  234.         if (dot > best)
  235.         {
  236.             best = dot;
  237.             bestaxis = i;
  238.         }
  239.     }
  240.     
  241.     VectorCopy (baseaxis[bestaxis*3+1], xv);
  242.     VectorCopy (baseaxis[bestaxis*3+2], yv);
  243. }
  244.  
  245.  
  246. /*============================================================================= */
  247.  
  248.  
  249. /*
  250. =================
  251. ParseBrush
  252. =================
  253. */
  254. void ParseBrush (void)
  255. {
  256.     mbrush_t        *b;
  257.     mface_t        *f;
  258.     vec3_t        planepts[3];
  259.     vec3_t            t1, t2, t3;
  260.     int            i,j;
  261.     texinfo_t    tx;
  262.     double        d;
  263.     float        shift[2], rotate, scale[2];
  264.  
  265.     b = &mapbrushes[nummapbrushes];
  266.     nummapbrushes++;
  267.     b->next = mapent->brushes;
  268.     mapent->brushes = b;
  269.         
  270.     b->numfaces = 0;
  271.     do
  272.     {
  273.         if (!GetToken (true))
  274.             break;
  275.         if (!strcmp (token, "}") )
  276.             break;
  277.         
  278.     /* read the three point plane definition */
  279.         for (i=0 ; i<3 ; i++)
  280.         {
  281.             if (i != 0)
  282.                 GetToken (true);
  283.             if (strcmp (token, "(") )
  284.                 Error ("parsing brush");
  285.             
  286.             for (j=0 ; j<3 ; j++)
  287.             {
  288.                 GetToken (false);
  289.                 planepts[i][j] = atoi(token);
  290.             }
  291.             
  292.             GetToken (false);
  293.             if (strcmp (token, ")") )
  294.                 Error ("parsing brush");
  295.                 
  296.         }
  297.  
  298.     /* read the texturedef */
  299.         memset (&tx, 0, sizeof(tx));
  300.         GetToken (false);
  301.         tx.miptex = FindMiptex (token);
  302.         GetToken (false);
  303.         shift[0] = atoi(token);
  304.         GetToken (false);
  305.         shift[1] = atoi(token);
  306.         GetToken (false);
  307.         rotate = atoi(token);    
  308.         GetToken (false);
  309.         scale[0] = atof(token);
  310.         GetToken (false);
  311.         scale[1] = atof(token);
  312.  
  313.         /* if the three points are all on a previous plane, it is a */
  314.         /* duplicate plane */
  315.         for (j=0 ; j<b->numfaces ; j++)
  316.         {
  317.             for (i=0 ; i<3 ; i++)
  318.             {
  319.                 d = DotProduct(planepts[i],b->faces[j].plane.normal)
  320.                 - b->faces[j].plane.dist;
  321.                 if (d < -ON_EPSILON || d > ON_EPSILON)
  322.                     break;
  323.             }
  324.             if (i==3)
  325.                 break;
  326.         }
  327.         if (j<b->numfaces)        
  328.         {
  329.             ShowWarningEntry("Brush with duplicate plane");
  330.             sleep(1);
  331.                         continue;
  332.         }
  333.  
  334.         f = &b->faces[b->numfaces];
  335.         b->numfaces++;
  336.         
  337.     /* convert to a vector / dist plane */
  338.         for (j=0 ; j<3 ; j++)
  339.         {
  340.             t1[j] = planepts[0][j] - planepts[1][j];
  341.             t2[j] = planepts[2][j] - planepts[1][j];
  342.             t3[j] = planepts[1][j];
  343.         }
  344.         
  345.         CrossProduct(t1,t2, f->plane.normal);
  346.         if (VectorCompare (f->plane.normal, vec3_origin))
  347.         {
  348.             ShowWarningEntry("Brush plane with no normal");
  349.             sleep(1);
  350.                         b->numfaces--;
  351.             break;
  352.         }
  353.         VectorNormalize (f->plane.normal);
  354.         f->plane.dist = DotProduct (t3, f->plane.normal);
  355.  
  356.     /* */
  357.     /* fake proper texture vectors from QuakeEd style */
  358.     /* */
  359.         {
  360.             vec3_t    vecs[2];
  361.             int        sv, tv;
  362.             float    ang, sinv, cosv;
  363.             float    ns, nt;
  364.             
  365.             TextureAxisFromPlane(&f->plane, vecs[0], vecs[1]);
  366.         
  367.             if (!scale[0])
  368.                 scale[0] = 1;
  369.             if (!scale[1])
  370.                 scale[1] = 1;
  371.         
  372.         
  373.         /* rotate axis */
  374.             if (rotate == 0)
  375.                 { sinv = 0 ; cosv = 1; }
  376.             else if (rotate == 90)
  377.                 { sinv = 1 ; cosv = 0; }
  378.             else if (rotate == 180)
  379.                 { sinv = 0 ; cosv = -1; }
  380.             else if (rotate == 270)
  381.                 { sinv = -1 ; cosv = 0; }
  382.             else
  383.             {    
  384.                 ang = rotate / 180 * Q_PI;
  385.                 sinv = sin(ang);
  386.                 cosv = cos(ang);
  387.             }
  388.         
  389.             if (vecs[0][0])
  390.                 sv = 0;
  391.             else if (vecs[0][1])
  392.                 sv = 1;
  393.             else
  394.                 sv = 2;
  395.                         
  396.             if (vecs[1][0])
  397.                 tv = 0;
  398.             else if (vecs[1][1])
  399.                 tv = 1;
  400.             else
  401.                 tv = 2;
  402.                             
  403.             for (i=0 ; i<2 ; i++)
  404.             {
  405.                 ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
  406.                 nt = sinv * vecs[i][sv] +  cosv * vecs[i][tv];
  407.                 vecs[i][sv] = ns;
  408.                 vecs[i][tv] = nt;
  409.             }
  410.         
  411.             for (i=0 ; i<2 ; i++)
  412.                 for (j=0 ; j<3 ; j++)
  413.                     tx.vecs[i][j] = vecs[i][j] / scale[i];
  414.         
  415.             tx.vecs[0][3] = shift[0];
  416.             tx.vecs[1][3] = shift[1];
  417.         }
  418.     
  419.     /* unique the texinfo */
  420.         f->texinfo = FindTexinfo (&tx);        
  421.     } while (1);
  422. }
  423.  
  424. /*
  425. ================
  426. ParseEntity
  427. ================
  428. */
  429. qboolean    ParseEntity (void)
  430. {
  431.     if (!GetToken (true))
  432.         return false;
  433.  
  434.     if (strcmp (token, "{") )
  435.         Error ("ParseEntity: { not found");
  436.     
  437.     if (num_entities == MAX_MAP_ENTITIES)
  438.         Error ("num_entities == MAX_MAP_ENTITIES");
  439.  
  440.     mapent = &entities[num_entities];
  441.     num_entities++;
  442.     
  443.     do
  444.     {
  445.         if (!GetToken (true))
  446.             Error ("ParseEntity: EOF without closing brace");
  447.         if (!strcmp (token, "}") )
  448.             break;
  449.         if (!strcmp (token, "{") )
  450.             ParseBrush ();
  451.         else
  452.             ParseEpair ();
  453.     } while (1);
  454.     
  455.     GetVectorForKey (mapent, "origin", mapent->origin);
  456.     return true;
  457. }
  458.  
  459. /*
  460. ================
  461. LoadMapFile
  462. ================
  463. */
  464. void LoadMapFile (char *filename)
  465. {
  466.     char    *buf;
  467.         
  468.     ShowStatusEntry("Loading map file.");
  469.  
  470.         LoadFile (filename, (void **)&buf);
  471.  
  472.     ShowTempEntry("Parsing loaded map text.");
  473.  
  474.     StartTokenParsing (buf);
  475.     
  476.     num_entities = 0;
  477.     
  478.     while (ParseEntity ())
  479.     {
  480.     }
  481.     
  482.     free (buf);
  483.     
  484.     ShowTempEntry("Map file loaded and parsed.");
  485. }
  486.  
  487. void PrintEntity (entity_t *ent)
  488. {
  489.     epair_t    *ep;
  490.     
  491.     for (ep=ent->epairs ; ep ; ep=ep->next)
  492.         printf ("%20s : %s\n", ep->key, ep->value);
  493. }
  494.  
  495.  
  496. char     *ValueForKey (entity_t *ent, char *key)
  497. {
  498.     epair_t    *ep;
  499.     
  500.     for (ep=ent->epairs ; ep ; ep=ep->next)
  501.         if (!strcmp (ep->key, key) )
  502.             return ep->value;
  503.     return "";
  504. }
  505.  
  506. void     SetKeyValue (entity_t *ent, char *key, char *value)
  507. {
  508.     epair_t    *ep;
  509.     
  510.     for (ep=ent->epairs ; ep ; ep=ep->next)
  511.         if (!strcmp (ep->key, key) )
  512.         {
  513.             strcpy (ep->value, value);
  514.             return;
  515.         }
  516.     ep = malloc (sizeof(*ep));
  517.     ep->next = ent->epairs;
  518.     ent->epairs = ep;
  519.     strcpy (ep->key, key);
  520.     strcpy (ep->value, value);
  521. }
  522.  
  523. float    FloatForKey (entity_t *ent, char *key)
  524. {
  525.     char    *k;
  526.     
  527.     k = ValueForKey (ent, key);
  528.     return atof(k);
  529. }
  530.  
  531. void     GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
  532. {
  533.     char    *k;
  534.     
  535.     k = ValueForKey (ent, key);
  536.     sscanf (k, "%lf %lf %lf", &vec[0], &vec[1], &vec[2]);
  537. }
  538.  
  539.  
  540. void WriteEntitiesToString (void)
  541. {
  542.     char    *buf, *end;
  543.     epair_t    *ep;
  544.     char    line[128];
  545.     int        i;
  546.     
  547.     buf = dentdata;
  548.     end = buf;
  549.     *end = 0;
  550.     
  551.     for (i=0 ; i<num_entities ; i++)
  552.     {
  553.         ep = entities[i].epairs;
  554.         if (!ep)
  555.             continue;    /* ent got removed */
  556.         
  557.         strcat (end,"{\n");
  558.         end += 2;
  559.                 
  560.         for (ep = entities[i].epairs ; ep ; ep=ep->next)
  561.         {
  562.             sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value);
  563.             strcat (end, line);
  564.             end += strlen(line);
  565.         }
  566.         strcat (end,"}\n");
  567.         end += 2;
  568.  
  569.         if (end > buf + MAX_MAP_ENTSTRING)
  570.             Error ("Entity text too long");
  571.     }
  572.     entdatasize = end - buf + 1;
  573. }
  574.  
  575.